package com.tanhua.app.service;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.tanhua.api.db.UserInfoApi;
import com.tanhua.api.mongo.CommentApi;
import com.tanhua.api.mongo.VideoApi;
import com.tanhua.app.interceptor.UserHolder;
import com.tanhua.domain.db.User;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.mongo.Comment;
import com.tanhua.domain.mongo.FollowUser;
import com.tanhua.domain.mongo.Video;
import com.tanhua.domain.vo.CommentVo;
import com.tanhua.domain.vo.PageBeanVo;
import com.tanhua.domain.vo.VideoVo;
import com.tanhua.template.OssTemplate;
import com.tanhua.utils.RelativeDateFormat;
import org.apache.dubbo.config.annotation.Reference;
import org.bson.types.ObjectId;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class VideoService {

    @Reference
    private VideoApi videoApi;
    @Reference
    private UserInfoApi userInfoApi;
    @Reference
    private CommentApi commentApi;
    @Autowired
    private OssTemplate ossTemplate;

    //准备一个客户端对象
    @Autowired
    private FastFileStorageClient fastClient;
    //准备一个nginx对象
    @Autowired
    private FdfsWebServer webServer;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    //小视频的查询（使用redis）
    @Cacheable(value = "video", key = "#page+'_'+#pagesize")  //要求：方法的返回值必须实现了序列化接口
    public PageBeanVo findVideo(Integer page, Integer pagesize) {
        User user = UserHolder.getUser();
        // 获取video的分页数据
        PageBeanVo pb = findFromBidData(user.getId(), page, pagesize);
        if (pb == null) {
            pb = videoApi.findVideo(page, pagesize);
        }
        System.out.println("方法执行：小视频是从mongdb获取");

        List<Video> items = (List<Video>) pb.getItems();

        List<VideoVo> videoVoList = new ArrayList();
        if (CollectionUtil.isNotEmpty(items)) {
            for (Video video : items) {
                // 获取userInfo的数据
                UserInfo userInfo = userInfoApi.findUserInfoVo(video.getUserId());
                // 封装数据给videoVo(页面要的)
                VideoVo videoVo = new VideoVo();
                BeanUtils.copyProperties(userInfo, videoVo);
                //手动封装userinfo的id
                videoVo.setUserId(userInfo.getId());
                BeanUtils.copyProperties(video, videoVo);
                //手动封装id
                videoVo.setId(video.getId().toString());
                //手动封装视频封面
                videoVo.setCover(video.getPicUrl());
                //手动封装视频说明
                videoVo.setSignature(video.getText());
                videoVo.setLikeCount(video.getLikeCount());
                videoVo.setCommentCount(video.getCommentCount());
                System.out.println(video.getCommentCount());
                // 是否点赞


                if (stringRedisTemplate.hasKey(StrUtil.format("video_like_comment_{}_{}", UserHolder.getUser().getId()
                        , video.getUserId()))) {
                    // 是否关注
                    videoVo.setHasLiked(0);
                } else {
                    // 是否关注
                    videoVo.setHasLiked(1);
                }
                if (stringRedisTemplate.hasKey(StrUtil.format("follow_user_{}_{}", UserHolder.getUser().getId()
                        , video.getUserId()))) {
                    // 是否关注
                    videoVo.setHasFocus(1);
                } else {
                    // 是否关注
                    videoVo.setHasFocus(0);
                }

                videoVoList.add(videoVo);
            }
        }
        // 封装分页进行返回
        for (VideoVo videoVo : videoVoList) {
            Integer commentCount = videoVo.getCommentCount();
            System.out.println(commentCount);
        }
        pb.setItems(videoVoList);
        return pb;
    }

    private PageBeanVo findFromBidData(Long id, Integer page, Integer pagesize) {
        System.out.println("查询redis");
        //根据大数据提供的redis中获取数据
        String values = stringRedisTemplate.opsForValue().get("QUANZI_VIDEO_RECOMMEND_" + id);
        System.out.println(values);
        if (StringUtils.isEmpty(values)) {
            return null;
        }
        String[] vidStr = values.split(",");
        //分页的数据
        int count = vidStr.length; //数组角标的长度就是总条数
        //起始数据
        int start = (page - 1) * pagesize;
        if (start > count) {
            return null;
        }
        int end = page * pagesize;
        if (end > count) {
            end = count;
        }
        List<Video> list = new ArrayList<>();
        for (int i = start; i < end; i++) {
            Video video = videoApi.findbyVid(Long.parseLong(vidStr[i]));
            list.add(video);
        }

        return new PageBeanVo(page, pagesize, (long) count, list);
    }

    //小视频的发布
    @CacheEvict(value = "video", allEntries = true) //小视频改变了 redis中的数据会清理
    public ResponseEntity saveVideo(MultipartFile videoThumbnail, MultipartFile videoFile) throws Exception {

        //1 将小视频的封面图片上传oss（地址）
        String imgUrl = ossTemplate.upload(videoThumbnail.getOriginalFilename(), videoThumbnail.getInputStream());

        //2 将小视频的内容上传fastDfs（地址）
        //1 上传文件的输入流
        //2 上传文件大小
        //3 上传文件的扩展名  FileUtil.extName(file)
        //4 上传文件的属性 设置为null即可
        StorePath storePath = fastClient.uploadFile(videoFile.getInputStream(), videoFile.getSize(),
                FileUtil.extName(videoFile.getOriginalFilename()), null);

        String videoUrl = webServer.getWebServerUrl() + storePath.getFullPath();

        //3 创建video对象
        Video video = new Video();
        // 小视频的创建时间
        video.setCreated(System.currentTimeMillis());
        // 小视频的发布用户
        video.setUserId(UserHolder.getUser().getId());
        // 小视频的描述
        video.setText("震惊，一男子夜奔...");
        // 小视频的封面图片地址
        video.setPicUrl(imgUrl);
        // 小视频的地址
        video.setVideoUrl(videoUrl);
        //4 保存video对象到mongodb中
        videoApi.save(video);


        return ResponseEntity.ok(null);
    }

    //小视频作者的关注
    @CacheEvict(value = "video", allEntries = true)
    public ResponseEntity saveGz(Long uid) {

        //创建实体设置属性
        FollowUser followUser = new FollowUser();
        followUser.setCreated(System.currentTimeMillis());
        followUser.setUserId(UserHolder.getUser().getId());
        followUser.setFollowUserId(uid);

        //保存实体
        videoApi.saveGz(followUser);


        //redis做标记关注过
        stringRedisTemplate.opsForValue().set(StrUtil.format("follow_user_{}_{}", UserHolder.getUser().getId()
                , uid), "1");


        return ResponseEntity.ok(null);
    }

    // 关注撤销
    @CacheEvict(value = "video", allEntries = true)
    public ResponseEntity removeGz(Long uid) {

        videoApi.removeGz(UserHolder.getUser().getId(), uid);

        stringRedisTemplate.delete(StrUtil.format("follow_user_{}_{}", UserHolder.getUser().getId()
                , uid));
        return ResponseEntity.ok(null);
    }

    //小视频点赞
    @CacheEvict(value = "video", allEntries = true)
    public ResponseEntity likeVideo(String publishId) {
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(publishId));
        comment.setPubType(2); ////评论内容类型： 1-对圈子动态操作 2-对视频操作 3-对评论操作
        comment.setCommentType(1); //评论类型，1-点赞，2-评论，3-喜欢
        Long userId = UserHolder.getUser().getId();
        comment.setUserId(userId);
        //添加
        Integer count = commentApi.save(comment);
        //redis中做标记
        stringRedisTemplate.opsForValue().set(StrUtil.format("video_like_comment_{}_{}",userId,publishId),"1");
        //return ResponseEntity.ok(count);
        return ResponseEntity.ok(null);
    }

    ////小视频取消点赞
    @CacheEvict(value = "video", allEntries = true)
    public ResponseEntity dislikeVideo(String publishId) {
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(publishId));
        comment.setPubType(2); ////评论内容类型： 1-对圈子动态操作 2-对视频操作 3-对评论操作
        comment.setCommentType(1); //评论类型，1-点赞，2-评论，3-喜欢
        Long userId = UserHolder.getUser().getId();
        comment.setUserId(userId);
        //删除
        Integer count = commentApi.remove(comment);

        //redis标记给删除
        stringRedisTemplate.delete(StrUtil.format("video_like_comment_{}_{}",userId,publishId));
        //return ResponseEntity.ok(count);
        return ResponseEntity.ok(null);
    }

    //查询评论列表视屏
    public ResponseEntity findplList(Integer page, Integer pagesize, String publishId) {
        // 查询comment的数据
        PageBeanVo pageBeanVo = commentApi.findCommentPage(page, pagesize, publishId,2);
        List<Comment> items = (List<Comment>) pageBeanVo.getItems();

        List<CommentVo> commentVoList = new ArrayList<>();
        if(CollectionUtil.isNotEmpty(items)){
            for (Comment comment : items) {
                //根据video拿到相关用户信息
                UserInfo userInfo = userInfoApi.findUserInfoVo(comment.getUserId());
                //封装页面需要的Vo
                CommentVo commentVo = new CommentVo();
                BeanUtils.copyProperties(comment,commentVo);
                BeanUtils.copyProperties(userInfo,commentVo);
                commentVo.setCreateDate(RelativeDateFormat.format(new Date(comment.getCreated())));
//                commentVo.setId(userInfo.getId().toString());
//                System.out.println(commentVo.getId());
                commentVoList.add(commentVo);
            }
        }
        pageBeanVo.setItems(commentVoList);
        return ResponseEntity.ok(pageBeanVo);
    }

    //发布评论
    public ResponseEntity savepl(String text, String publishId) {
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(publishId));
        comment.setPubType(2); //评论内容类型： 1-对圈子动态操作 2-对视频操作 3-对评论操作
        comment.setCommentType(2); //评论类型，1-点赞，2-评论，3-喜欢
        comment.setContent(text); //评论内容
        Long userId = UserHolder.getUser().getId();
        comment.setUserId(userId);

        //保存到mongodb
        commentApi.save(comment);
        //return ResponseEntity.ok(count);
        return ResponseEntity.ok(null);
    }

    //评论点赞
    public ResponseEntity likeComments(String publishId) {
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(publishId));
        comment.setPubType(3); ////评论内容类型： 1-对圈子动态操作 2-对视频操作 3-对评论操作
        comment.setCommentType(1); //评论类型，1-点赞，2-评论，3-喜欢
        Long userId = UserHolder.getUser().getId();
        comment.setUserId(userId);
        //添加
        Integer count = commentApi.save(comment);
        //redis中做标记
        stringRedisTemplate.opsForValue().set(StrUtil.format("Comments_like_comment_{}_{}",userId,publishId),"1");
        System.out.println(count);
        return ResponseEntity.ok(count);
    }

    //评论取消点赞
    public ResponseEntity dislikeComments(String publishId) {
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(publishId));
        comment.setPubType(3); ////评论内容类型： 1-对圈子动态操作 2-对视频操作 3-对评论操作
        comment.setCommentType(1); //评论类型，1-点赞，2-评论，3-喜欢
        Long userId = UserHolder.getUser().getId();
        comment.setUserId(userId);
        //删除
        Integer count = commentApi.remove(comment);

        //redis标记给删除
        stringRedisTemplate.delete(StrUtil.format("Comments_like_comment_{}_{}",userId,publishId));
        System.out.println(count);
        return ResponseEntity.ok(count);
    }
}
